﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Extentions;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Senparc.Weixin.MP.AdvancedAPIs.OAuth;
using TrainingReminderSystem.Dal;
using TrainingReminderSystem.Model;
using Z.EntityFramework.Plus;

namespace TrainingReminderSystem.Bll
{
    /// <summary>
    /// 手机端客户基础类
    /// </summary>
    public partial class CustomerLoginedBll : BaseBll
    {
        #region 构造函数

        public CustomerLoginedBll() : base()
        {
        }

        /// <summary>
        /// 线程内只能调用此构造函数
        /// 多语言调用
        /// </summary>
        /// <param name="sessionID"></param>
        public CustomerLoginedBll(string sessionID) : base(sessionID)
        {
        }

        #endregion

        #region 登录信息相关

        #region 请求用户Token信息

        /// <summary>
        /// token名称
        /// 全小写是因为有android浏览器的会传入小写
        /// </summary>
        public const string CustomerTokenKey = "customerwebapitoken";

        /// <summary>
        /// 设备唯一标识
        /// </summary>
        private const string DeviceKey = "device";

        /// <summary>
        /// 获取token字符串
        /// </summary>
        public static string Token
        {
            get
            {
                //Header里面去取,取不到就在cookie里面取
                var c = ExHttpContext.Current;
                if (c == null || c.Request == null) return string.Empty;
                string token = c.Request.Headers[CustomerTokenKey];
                if (string.IsNullOrEmpty(token))
                {
                    token = c.Request.Cookies[CustomerTokenKey];
                    if (!string.IsNullOrEmpty(token))
                    {
                        token = System.Web.HttpUtility.UrlDecode(token);
                    }
                }
                return token;
            }
        }

        #endregion

        #region Device唯一请求标识

        /// <summary>
        /// Device唯一请求标识
        /// </summary>
        public static string Device
        {
            get
            {
                var c = ExHttpContext.Current;
                if (c == null || c.Request == null) return string.Empty;
                string device = c.Request.Headers[DeviceKey];
                return device;
            }
        }

        #endregion

        #region 请求用户信息

        /// <summary>
        /// 缓存名字
        /// </summary>
        private const string CacheCurrentCustomer = "CacheCurrentCustomer";

        /// <summary>
        /// 当前客户,绑定了客户的才能登录
        /// </summary>
        public static SysCustomer CurrentCustomer
        {
            get
            {
                var obj = CacheHelper.GetCache(CacheCurrentCustomer + Token) as SysCustomer;
                return obj;
            }
        }

        /// <summary>
        /// 当前店铺
        /// </summary>
        public static SysStore CurrentStore
        {
            get
            {
                var openID = CurrentOpenID;
                if (openID != null)
                {
                    return openID.SysStore;
                }
                var customer = CurrentCustomer;
                if (customer == null) return null;
                return customer.SysStore;
            }
        }

        /// <summary>
        /// 是否能看到手机号
        /// </summary>
        public static bool CanSeePhone
        {
            get
            {
                var current = PcLoginedBll.CurrentEmployee;
                if (current == null) return false;
                return current.CanSeePhone;
            }
        }

        #region 缓存相关

        protected static void SetCurrentCustomer(string token, SysCustomer obj)
        {
            if (obj != null) obj.Token = token;
            CacheHelper.SetRelativeCache(CacheCurrentCustomer + token, obj);
        }

        /// <summary>
        /// 清除缓存
        /// </summary>
        /// <param name="token"></param>
        public static void ClearCache(string token)
        {
            CacheHelper.RemoveCache(CacheCurrentCustomer + token);
        }

        private static object _sync = new object();

        /// <summary>
        /// 清除客户缓存信息
        /// </summary>
        /// <param name="sysCustomerID"></param>
        protected static void ClearCache(int sysCustomerID)
        {
            lock (_sync)
            {
                try
                {
                    var list = CacheHelper.GetList(CacheCurrentCustomer + sysCustomerID + SysCustomerBll.TokenSplit);
                    foreach (var item in list)
                    {
                        CacheHelper.RemoveCache(item.Key);
                    }
                }
                catch (Exception ex) { }
            }
        }

        #endregion

        #endregion

        #region 微信登录信息

        #region 微信OpenID信息

        /// <summary>
        /// token名称
        /// 全小写是因为有android浏览器的会传入小写
        /// </summary>
        public const string WechatCustomerTokenKey = "wechatcustomerwebapitoken";

        /// <summary>
        /// 获取token字符串
        /// </summary>
        public static string WechatToken
        {
            get
            {
                //Header里面去取,取不到就在cookie里面取
                var c = ExHttpContext.Current;
                if (c == null || c.Request == null) return string.Empty;
                string token = c.Request.Headers[WechatCustomerTokenKey];
                if (string.IsNullOrEmpty(token))
                {
                    token = c.Request.Cookies[WechatCustomerTokenKey];
                    if (!string.IsNullOrEmpty(token))
                    {
                        token = System.Web.HttpUtility.UrlDecode(token);
                    }
                }
                return token;
            }
            set
            {
                var c = ExHttpContext.Current;
                if (c == null || c.Request == null) return;
                c.Request.Headers.Remove(WechatCustomerTokenKey);
                c.Request.Headers.Add(WechatCustomerTokenKey, value);
            }
        }

        /// <summary>
        /// 缓存名字
        /// </summary>
        private const string CacheSysCustomerOpenID = "CacheSysCustomerOpenID";

        /// <summary>
        /// 当前OpenID
        /// </summary>
        public static SysCustomerOpenID CurrentOpenID
        {
            get
            {
                var obj = CacheHelper.GetCache(CacheSysCustomerOpenID + WechatToken) as SysCustomerOpenID;
                return obj;
            }
        }

        /// <summary>
        /// 设置OpenID
        /// </summary>
        /// <param name="wechatToken"></param>
        /// <param name="val"></param>
        protected static void SetCurrentOpenID(string wechatToken, SysCustomerOpenID val)
        {
            CacheHelper.SetRelativeCache(CacheSysCustomerOpenID + wechatToken, val);
        }

        #endregion

        #endregion

        #endregion

        #region 数据库访问对象

        /// <summary>
        /// 数据库访问对象
        /// </summary>
        public static DbEntities Db
        {
            get
            {
                DbEntities db = DbEntitiesHelper.GetDbEntities(false);
                //基础表才加
                var currentCustomer = CurrentCustomer;
                var currentOpenID = CurrentOpenID;
                bool hasLoginInfo = currentOpenID != null || currentCustomer != null;
                if (hasLoginInfo)
                {
                    int? customerIDNull = currentOpenID != null ? currentOpenID.SysCustomerID : currentCustomer.SysCustomerID;
                    int storeID = currentOpenID != null ? currentOpenID.GetParentID() : currentCustomer.GetParentID();
                    var storeIDList = GetAllStoreIDCache(storeID, db);

                    int customerID = customerIDNull != null ? customerIDNull.Value : 0;

                    if (customerID > 0)
                    {
                        EfFilterHelper.BuildFilterInt(db, nameof(SysCustomer.SysCustomerID), customerID, false);
                    }

                    EfFilterHelper.BuildFilterIntList(db, nameof(SysCustomer.SysStoreID), storeIDList, false);

                    //db.Filter<SysDic>(nameof(SysDic) + nameof(SysStore.SysStoreID), m => m.Where(n => storeIDList.Contains(n.SysStoreID)));
                    //db.Filter<SysSetting>(nameof(SysSetting) + nameof(SysSetting.SysStoreID), m => m.Where(n => storeIDList.Contains(n.SysStoreID)));
                    //db.Filter<SysRolePost>(nameof(SysRolePost) + nameof(SysRolePost.SysStoreID),
                    //    m => m.Where(n => storeIDList.Contains(n.SysStoreID)));
                }

                return db;
            }
        }

        public static DbEntities DbNoFilter
        {
            get
            {
                DbEntities db = DbEntitiesHelper.GetDbEntities(false);
                return db;
            }
        }

        #region 相关店铺ID缓存方法

        /// <summary>
        /// 缓存相关店铺ID
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        internal static List<int> SetAllStoreIDCache(int id, DbEntities db)
        {
            return PcLoginedBll.SetAllStoreIDCache(id, db);
        }

        /// <summary>
        /// 得到所有店铺ID
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal static List<int> GetAllStoreIDCache(int id, DbEntities db)
        {
            return PcLoginedBll.GetAllStoreIDCache(id, db);
        }

        /// <summary>
        /// 清除缓存
        /// </summary>
        /// <param name="id"></param>
        protected static void ClearAllStoreIDCache(int id)
        {
            PcLoginedBll.ClearAllStoreIDCache(id);
        }

        #endregion

        #endregion

        #region demo演示帐号的权限验证(以前:记录原始数据的操作日志)

        /// <summary>
        /// demo演示帐号的权限验证
        /// 记录原始数据的操作日志;做为日志功能废弃了的
        /// </summary>
        /// <param name="db"></param>
        /// <param name="model"></param>
        /// <param name="enumLogType"></param>
        /// <param name="tblName"></param>
        protected string AddLog(DbEntities db, object model, EnumLogType enumLogType, string tblName = "")
        {
            var sysCustomer = CurrentCustomer;
            Type type = GetModelType(model);
            if (sysCustomer != null && sysCustomer.IsDemo)
            {
                if (enumLogType == EnumLogType.删除)
                {
                    return comLan.GetString("DemoLogin.NoDel");
                }

                if ((enumLogType == EnumLogType.登录 || enumLogType == EnumLogType.注销) == false)
                {
                    //非登录注销的
                    if (type == typeof(SysCustomer) || type == typeof(SysRolePost) || type == typeof(SysSetting) || type == typeof(SysStore))
                    {
                        return comLan.GetString("DemoLogin.NoCustomer");
                    }
                }
            }

            return null;
            try
            {
                var c = ExHttpContext.Current;
                //多线程调用添加修改等方法,c可能为null,并且c.Session会报错
                //if (c == null || c.Request == null || c.Session == null) return null;
                var request = c?.Request;
                string url = request?.ExUrl();
                //string post = c.Request.Form.ExToString();//要报错
                string post = request?.ExBodyString();
                if (string.IsNullOrEmpty(url)) url = string.Empty;
                if (string.IsNullOrEmpty(post)) post = string.Empty;
                //已经存在过url和form了,就不再添加了
                string addedKey = "getPostString" + SessionID;
                string getPostString = CacheHelper.GetCache(addedKey) as string;
                string getPost = url + post;
                if (getPostString != null && getPostString == getPost)
                {
                    return null;
                }
                CacheHelper.SetAbsoluteCache(addedKey, getPost, 10);
                SysLog log = new SysLog();
                log.GetUrl = url;
                log.PostForm = post;
                log.BeforeVal = string.Empty;
                log.PostVal = string.Empty;
                log.EnumLogType = enumLogType;
                log.CreateDate = DateTime.Now;
                log.SysEmployeeID = null; //sysCustomer?.SysCustomerID;
                log.UserAgent = request?.UserAgent();
                //调用IP地址
                log.IPAddress = ToolHelper.GetIpAddress();
                if (enumLogType == EnumLogType.登录)
                {
                    log.SysEmployeeID = null;//Convert.ToInt32(model);
                    db.SysLog.Add(log);
                    //db.SaveChanges();
                    return null;
                }
                //model.ExToJson极度耗费性能,会把所有关联都给搞出来
                if (model != null)
                {
                    if (type != null)
                    {
                        if (!string.IsNullOrEmpty(tblName))
                        {
                            log.TblName = tblName;
                        }
                        else
                        {
                            log.TblName = type.FullName;
                        }
                    }

                    var ps = type.GetProperties();
                    PropertyInfo p = ps.FirstOrDefault(m =>
                        m.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() != null);
                    if (p == null)
                    {
                        string pk = "id";
                        var tempStr = log.TblName.ToLower();
                        p = ps.FirstOrDefault(m => m.Name.ToLower() == (tempStr + pk));
                        if (p == null)
                        {
                            p = ps.FirstOrDefault(m => m.Name.ToLower().Contains(pk));
                        }
                    }

                    if (p != null) log.TblID = Convert.ToInt32(p.GetValue(model));
                }

                db.SysLog.Add(log);
                //db.SaveChanges();
            }
            catch //(Exception e)
            {
                //Task调用新增数据库的时候,session会没有,会报错,直接忽略
                //e.ExLogError();
            }
            return null;
        }

        #endregion

        #region 当前信息

        /// <summary>
        /// 当前信息
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentOther()
        {
            return PcLoginedBll.GetCurrentOther();
        }

        #endregion
    }
}
